﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TestPlanWordWriter.Common;
using Microsoft.TeamFoundation.Client;
using System.Runtime.Remoting.Messaging;
using System.Threading;
using System.Threading.Tasks;

namespace TestPlanWordWriter.UI
{
    public partial class TestInfoProgressForm : Form
    {
        public TfsTeamProjectCollection TeamProjectCollection { get; set; }
        public string TeamProjectName { get; set; }
        public List<UIControlInfo> Plans { get; set; }

        public List<UIPlanInfo> TestPlansInfo { get; private set; }

        private CancellationTokenSource cts = new CancellationTokenSource();

        public TestInfoProgressForm()
        {
            InitializeComponent();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            cts.Cancel();
        }


        private void TestInfoProgressForm_Load(object sender, EventArgs e)
        {
            lblTestCasesProgress.Text = string.Empty;
            lblTestCaseInfo.Text = string.Empty;
            lblTestPlanInfo.Text = string.Empty;
            lblTestSuiteInfo.Text = string.Empty;

            DoWork();
        }

        private void DoWork()
        {
            if (this.Plans != null)
            {
                TaskScheduler taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 

                TestPlanInfoSimpleBuilder planBuilder = new TestPlanInfoSimpleBuilder();
                planBuilder.TestSuitesProgressChanged += (sender, eventArgs) => RefreshTestSuitesProgress(taskScheduler, eventArgs);
                planBuilder.TestCasesProgressChanged += (sender, eventArgs) => RefreshTestCasesProgress(taskScheduler, eventArgs);
                planBuilder.BeforeTestPlanProcess += (sender, eventArgs) => RefreshBeforeTestPlan(taskScheduler, eventArgs);
                planBuilder.BeforeTestSuiteProcess += (sender, eventArgs) => RefreshBeforeTestSuite(taskScheduler, eventArgs);
                planBuilder.BeforeTestCaseProcess += (sender, eventArgs) => RefreshBeforeTestCase(taskScheduler, eventArgs);

                Task t = Task.Factory.StartNew(() =>
                {
                    try
                    {

                        this.TestPlansInfo = new List<UIPlanInfo>();

                        int currentTestPlan = 0;
                        int totalTestPlans = this.Plans.Count;
                        foreach (UIControlInfo planUIMetaInfo in this.Plans)
                        {
                            RefreshTestPlansProgress(taskScheduler, currentTestPlan, totalTestPlans);

                            int planId = planUIMetaInfo.PlanId;

                            UIPlanInfo planUIInfo = new UIPlanInfo();
                            planUIInfo.ControlInfo = planUIMetaInfo;
                            planUIInfo.PlanInfo = planBuilder.BuildPlanInfo(this.TeamProjectCollection, this.TeamProjectName, planId, cts.Token);
                            
                            this.TestPlansInfo.Add(planUIInfo);

                            currentTestPlan++;
                        }

                        Task endWorkTask = Task.Factory.StartNew(() =>
                        {
                            this.DialogResult = System.Windows.Forms.DialogResult.OK;
                            this.Close();
                        }, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
                        endWorkTask.Wait();

                    }
                    catch (OperationCanceledException) { }
                }, cts.Token);
            }
        }

        private void RefreshBeforeTestPlan(TaskScheduler taskScheduler, BeforeTestPlanProcessEventArgs eventArgs)
        {
            string progressMessage = string.Format("Processing test plan {0}", eventArgs.TestPlan.Name);
            Task refreshProgressTask = Task.Factory.StartNew(() =>
            {
                lblTestPlanInfo.Text = progressMessage;
            }, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
            refreshProgressTask.Wait();
        }

        private void RefreshBeforeTestSuite(TaskScheduler taskScheduler, BeforeTestSuiteProcessEventArgs eventArgs)
        {
            string progressMessage = string.Format("Processing test suite {0}", eventArgs.TestSuite.Title);
            Task refreshProgressTask = Task.Factory.StartNew(() =>
            {
                lblTestSuiteInfo.Text = progressMessage;
            }, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
            refreshProgressTask.Wait();
        }


        private void RefreshTestPlansProgress(TaskScheduler taskScheduler, int currentPlan, int totalPlans)
        {
            string progressMessage = string.Format("Processed {0} of {1} test plans", currentPlan, totalPlans);
            Task refreshProgressTask = Task.Factory.StartNew(() =>
            {
                lblTestPlansProgress.Text = progressMessage;
                pgbPlansProgress.Maximum = totalPlans;
                pgbSuitesProgress.Value = 0;
                pgbPlansProgress.Value = currentPlan;
            }, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
            refreshProgressTask.Wait();
        }

        private void RefreshBeforeTestCase(TaskScheduler taskScheduler, BeforeTestCaseProcessEventArgs eventArgs)
        {
            string progressMessage = string.Format("Processing test case {0}", eventArgs.TestCase.Title);
            Task refreshProgressTask = Task.Factory.StartNew(() =>
            {
                lblTestCaseInfo.Text = progressMessage;
            }, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
            refreshProgressTask.Wait();
        }

        private void RefreshTestCasesProgress(TaskScheduler taskScheduler, TestCasesInfoProgressChangedEventArgs eventArgs)
        {
            string progressMessage = string.Format("Processed {0} of {1} test cases", eventArgs.ProcessedTestCases, eventArgs.TotalTestCases);
            Task refreshProgressTask = Task.Factory.StartNew(() =>
            {
                lblTestCasesProgress.Text = progressMessage;
            }, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
            refreshProgressTask.Wait();
        }

        private void RefreshTestSuitesProgress(TaskScheduler taskScheduler, TestSuitesInfoProgressChangedEventArgs eventArgs)
        {
            string progressMessage = string.Format("Processed {0} of {1} test suites", eventArgs.ProcessedTestSuites, eventArgs.TotalTestSuites);
            Task refreshProgressTask = Task.Factory.StartNew(() =>
            {
                // Running on the UI thread
                lblTestSuitesProgress.Text = progressMessage;
                pgbSuitesProgress.Maximum = eventArgs.TotalTestSuites;
                pgbSuitesProgress.Value = eventArgs.ProcessedTestSuites;
            }, CancellationToken.None, TaskCreationOptions.None, taskScheduler);
            refreshProgressTask.Wait();
        }
    }
}
